/**
 * 系统名称: 企业财资
 * 模块名称: repair-boot
 * 类 名 称: QuartzJobServiceImpl.java
 * 软件版权: 恒生电子股份有限公司
 * 修改记录:
 * 修改人员:
 * 修改说明:
 * ============ ============================================
 * zhanghong 创建
 * ============ ============================================
 */
package com.mt.common.system.service.impl;

import com.mt.common.core.exception.BusinessException;
import com.mt.common.core.utils.EntityMapUtils;
import com.mt.common.system.entity.ScheduledTask;
import com.mt.common.system.service.QuartzJobService;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author zhanghong
 * @date 2023-03-20 11:15
 */
@Service
public class QuartzJobServiceImpl implements QuartzJobService {
    private static final Logger log = LoggerFactory.getLogger(QuartzJobServiceImpl.class);

    @Autowired
    private Scheduler scheduler;

    @Override
    public void addJob(String clazzName, String jobName, String groupName, String cronExp, Map<String, Object> param) throws SchedulerException {
        if(scheduler.getJobDetail(JobKey.jobKey(jobName,groupName))!=null){
            throw  new BusinessException("当前任务名称:"+jobName+",任务分组:"+groupName+"任务已经存在");
        }
        try {
            // 启动调度器，默认初始化的时候已经启动
//            scheduler.start();
            if (clazzName == null) {
                clazzName = "com.mt.common.system.entity.scheduledJob.ScheduledJob";
            }
            //构建job信息
            Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(clazzName);
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, groupName).build();
            //表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName).withSchedule(scheduleBuilder).build();
            //获得JobDataMap，写入数据
            if (param != null) {
                trigger.getJobDataMap().putAll(param);
                //jobDetail.getJobDataMap().putAll(param);
            }
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            log.error("创建任务失败", e);
        }
    }

    @Override
    public void pauseJob(String jobName, String groupName) {
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName, groupName));
        } catch (SchedulerException e) {
            log.error("暂停任务失败", e);
        }
    }

    @Override
    public void resumeJob(String jobName, String groupName) {
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName, groupName));
        } catch (SchedulerException e) {
            log.error("恢复任务失败", e);
        }
    }

    @Override
    public void runOnce(String jobName, String groupName) {
        try {
            scheduler.triggerJob(JobKey.jobKey(jobName, groupName));
        } catch (SchedulerException e) {
            log.error("立即运行一次定时任务失败", e);
        }
    }

    @Override
    public void updateJob(String jobName, String groupName, String cronExp, Map<String, Object> param) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (cronExp != null) {
                // 表达式调度构建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
                // 按新的cronExpression表达式重新构建trigger
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            }
            //JobKey jobKey = JobKey.jobKey(jobName, groupName);
            //JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            //修改map
            if (param != null) {
                trigger.getJobDataMap().putAll(param);
                //jobDetail.getJobDataMap().putAll(param);
            }
            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (Exception e) {
            log.error("更新任务失败", e);
        }
    }

    @Override
    public void deleteJob(String jobName, String groupName) {
        try {
            //暂停、移除、删除
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, groupName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, groupName));
            scheduler.deleteJob(JobKey.jobKey(jobName, groupName));
        } catch (Exception e) {
            log.error("删除任务失败", e);
        }
    }

    @Override
    public void startAllJobs() {
        try {
            scheduler.start();
        } catch (Exception e) {
            log.error("开启所有的任务失败", e);
        }
    }

    @Override
    public void pauseAllJobs() {
        try {
            scheduler.pauseAll();
        } catch (Exception e) {
            log.error("暂停所有任务失败", e);
        }
    }

    @Override
    public void resumeAllJobs() {
        try {
            scheduler.resumeAll();
        } catch (Exception e) {
            log.error("恢复所有任务失败", e);
        }
    }

    @Override
    public void shutdownAllJobs() {
        try {

            if (!scheduler.isShutdown()) {
                // 需谨慎操作关闭scheduler容器
                // scheduler生命周期结束，无法再 start() 启动scheduler
                scheduler.shutdown(true);
            }
        } catch (Exception e) {
            log.error("关闭所有的任务失败", e);
        }
    }

    @Override
    public List<ScheduledTask> findAll() {
        List<ScheduledTask> scheduledTasks = new ArrayList<>();
        try {
            GroupMatcher<TriggerKey> matcher = GroupMatcher.anyTriggerGroup();
            Set<TriggerKey> triggerKeys = scheduler.getTriggerKeys(matcher);
            Iterator<TriggerKey> iterator = triggerKeys.iterator();
            while (iterator.hasNext()){
                TriggerKey key = iterator.next();
                try {
                    Trigger trigger = scheduler.getTrigger(key);
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(key);
                    JobDataMap jobDataMap = trigger.getJobDataMap();
                    if (jobDataMap.size() == 0) {
                        jobDataMap.put("jobName", key.getName());
                        jobDataMap.put("jobGroup", key.getGroup());
                    }
                    ScheduledTask scheduledTask = EntityMapUtils.mapToObj(jobDataMap, ScheduledTask.class);
                    scheduledTask.setStatus(String.valueOf(triggerState.ordinal()));
                    scheduledTasks.add(scheduledTask);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return scheduledTasks;
    }
}
